package cc.co.cutenimy.nimyexplore.jdbc.metadata;

import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import cc.co.cutenimy.nimyexplore.model.metadata.JdbcType;
import cc.co.cutenimy.nimyexplore.model.metadata.NResultSetColumn;
import cc.co.cutenimy.nimyexplore.model.metadata.NSchema;
import cc.co.cutenimy.nimyexplore.model.metadata.ObjectFactory;

import com.google.inject.Inject;

/**
 * 
 * @author 234aini@gmail.com
 * 
 */
public class AutoMetaDataParser implements MetaDataParser {

	@Inject
	private final DatabaseMetaData databaseMetaData;

	@Inject
	private ResultSetMetaDataParser resultSetMetaDataParser;

	@Inject
	private ObjectFactory objectFactory;

	@Inject
	public AutoMetaDataParser(final DatabaseMetaData meta) {
		this.databaseMetaData = meta;
	}

	public List<NSchema> listSchemas() throws SQLException {
		DatabaseMetaData meta = getDatabaseMetaData();
		ResultSet result = meta.getSchemas();

		ResultSetMetaDataParser resultSetMetaDataParser = getResultSetMetaDataParser();
		resultSetMetaDataParser.setResultSetMetaData(result.getMetaData());
		List<NResultSetColumn> listColumns = resultSetMetaDataParser
				.listColumns();

		List<NSchema> list = new ArrayList<NSchema>(8);
		while (result.next()) {
			NSchema nSchema = getObjectFactory().createNSchema();
			nSchema.setType(JdbcType.SCHEMA);
			for (int i = 0; i < listColumns.size(); i++) {
				NResultSetColumn column = listColumns.get(i);
				if (isSchemaNameColumn(column)) {
					nSchema.setName((String) result.getObject(column
							.getColumnName()));
				}
			}
			list.add(nSchema);
		}
		return list;
	}

	/**
	 * For HSQL, the column name is 'TABLE_SCHEM', but maybe some other database
	 * are not use this literal value.
	 * 
	 * @param column
	 * @return
	 */
	protected boolean isSchemaNameColumn(final NResultSetColumn column) {
		return column.getColumnName().toLowerCase().matches(".*_sche[ma]");
	}

	public DatabaseMetaData getDatabaseMetaData() {
		return databaseMetaData;
	}

	public ResultSetMetaDataParser getResultSetMetaDataParser() {
		return resultSetMetaDataParser;
	}

	public void setResultSetMetaDataParser(
			ResultSetMetaDataParser resultSetMetaDataParser) {
		this.resultSetMetaDataParser = resultSetMetaDataParser;
	}

	public ObjectFactory getObjectFactory() {
		return objectFactory;
	}

	public void setObjectFactory(ObjectFactory objectFactory) {
		this.objectFactory = objectFactory;
	}

}
